﻿using System.Security.Claims;
using System.Text;
using System.IdentityModel.Tokens.Jwt;
using WLYT.Domain.Model;
using Microsoft.IdentityModel.Tokens;
using WLYT.Domain.Entries;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json.Linq;

namespace WLYT.Common
{
    public class JwtHelper
    {
        /// <summary>
        /// 生成token令牌
        /// </summary>
        /// <param name="claimInfo">要存储在token中的信息</param>
        /// <param name="tokenManagement"></param>
        /// <returns></returns>
        public static string CreateToken(Sys_User user)
        {
            List<Claim> claims = new()
            {
                new Claim(ClaimTypes.Sid, user.Id.ToString()),
                new Claim(ClaimTypes.Name, user.UserName ?? ""),
                new Claim(ClaimTypes.Role, user.RoleId.ToString()),
            };
            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(AppConfig.TokenAuthConfig.Secret));
            var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
            var jwtToken = new JwtSecurityToken(AppConfig.TokenAuthConfig.Issuer, AppConfig.TokenAuthConfig.Audience, claims,
                expires: DateTime.UtcNow.AddMinutes(AppConfig.TokenAuthConfig.AccessExpiration),
                signingCredentials: credentials);
            return new JwtSecurityTokenHandler().WriteToken(jwtToken);
        }


        /// <summary>
        /// 获取请求上下文Claims中的UserId
        /// </summary>
        /// <param name="httpContext">请求上下文</param>
        /// <returns></returns>
        public static int GetUserId(HttpContext httpContext)
        {
            int userId = 0;
            if (httpContext.User is null)
                return userId;
            if (!httpContext.User.Claims.Any())
                return userId;

            var claim = httpContext.User.Claims.FirstOrDefault(e => e.Type == ClaimTypes.Sid);
            if (claim is null)
                return userId;

            userId = Convert.ToInt32(claim.Value);
            return userId;
        }

        /// <summary>
        /// 获取请求上下文Claims中的Name名称
        /// </summary>
        /// <param name="httpContext">请求上下文</param>
        /// <returns></returns>
        public static string GetName(HttpContext httpContext)
        {
            string name = "";
            if (httpContext.User is null)
                return name;
            if (!httpContext.User.Claims.Any())
                return name;

            var claim = httpContext.User.Claims.FirstOrDefault(e => e.Type == ClaimTypes.Name);
            if (claim is null)
                return name;

            name = claim.Value;

            return name;
        }

        /// <summary>
        /// 解析token获取JwtSecurityToken对象
        /// </summary>
        /// <param name="token">token</param>
        /// <returns></returns>
        public static JwtSecurityToken GetSecurityToken(string token)
        {
            token = GetRemoveBearerToken(token);

            //解析token
            JwtSecurityToken jwtToken = new JwtSecurityTokenHandler().ReadJwtToken(token);

            return jwtToken;
        }

        /// <summary>
        /// 获取token中存储的信息
        /// </summary>
        /// <param name="httpContext">http数据上下文</param>
        /// <returns></returns>
        public static UserDto GetTokenPayload(HttpContext httpContext)
        {
            var token = httpContext.Request.Headers["Authorization"].ToString();
            return GetTokenPayload(token);
        }

        /// <summary>
        /// 获取token中存储的信息
        /// </summary>
        /// <param name="token">token令牌</param>
        /// <returns></returns>
        public static UserDto GetTokenPayload(string token)
        {
            token = GetRemoveBearerToken(token);
            JwtSecurityToken jwtToken = new JwtSecurityTokenHandler().ReadJwtToken(token);
            if (jwtToken == null)
            {
                throw new ArgumentNullException("解析token失败！");
            }
            UserDto tokenPayload = new UserDto()
            {
                Id = Convert.ToInt32(jwtToken.Payload[ClaimTypes.Sid]),
                UserName = jwtToken.Payload[ClaimTypes.Name].ToString(),
            };
            if (jwtToken.Payload[ClaimTypes.Role] != null)
                tokenPayload.RoleId = Convert.ToInt32(jwtToken.Payload[ClaimTypes.Role]);
            return tokenPayload;
        }

        /// <summary>
        /// 获取去除字符串开头Bearer的token令牌
        /// </summary>
        /// <param name="token">token令牌</param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException"></exception>
        public static string GetRemoveBearerToken(string token)
        {
            if (token.IsNullOrEmpty()) 
                throw new ArgumentNullException("传入的token为空!");

            if (token.StartsWith("Bearer "))
                return token.Replace("Bearer ", "");

            return token;
        }

    }
}
